# -*- coding:utf-8 -*-
"""
作者：小朱
日期：2023年08月29日
"""
from time import sleep

from selenium.common import NoAlertPresentException

from src import error
from selenium.webdriver.common.by import By
from src.Student import ParseJsonToObj, Student
from src.read_ini import IniConf
import requests
import json
import logging
import mimetypes
from selenium import webdriver

# 登录教务系统
def input_login_course(IniConfBoj, id, password):
    # 输入账户密码
    driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_login_user_id).clear()
    driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_login_user_id).send_keys(id)
    driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_login_password_id).clear()
    driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_login_password_id).send_keys(password)
    print("学号：" + id + "\t：提交密码\t" + password)
    # 确认提交
    before_url = driver.current_url
    driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_login_commit).click()
    sleep(float(IniConfBoj.mylocal_main_time))
    if before_url == driver.current_url:
        raise error.login_error_password(id, password)


# 进入教务系统
def enter_login(IniConfBoj):
    # 定位教务系统
    driver.find_element(By.CLASS_NAME, IniConfBoj.mylocal_educational_system_class).click()  # 定位元素并点击
    print("进入教务系统")
    # 跳转登录页面
    # 获取全部标签页
    window = driver.window_handles
    # 将激活标签页设置为最新的一项
    driver.switch_to.window(window.pop())


# 进入教务系统进入选课
def begin_select_course(IniConfBoj):
    # 跳转主控
    driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_mian_name).click()
    # 切换到主控
    frame = driver.find_elements(By.TAG_NAME, "iframe")
    iframe = driver.find_element(By.ID, frame[0].get_attribute('id'))  # 找到frmDesk这个房间
    driver.switch_to.frame(iframe)  # 进入到frmDesk这个房间
    # 点击网上选课
    driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_select_name).click()
    # 点击按计划开课
    XPath = '//div[text()="' + IniConfBoj.mylocal_educational_system_select_plan_name + '"]'
    driver.find_element(By.XPATH, XPath).click()
    if bool(IniConfBoj.mylocal_open_public_course_selection):
        # 点击第三个
        driver.find_element(By.XPATH, IniConfBoj.mylocal_educational_system_course_scope_xpath).click()


# 选课函数
def select_course(course, driver, IniConfBoj):
    frame = driver.find_elements(By.TAG_NAME, "iframe")
    iframe = driver.find_element(By.ID, frame[0].get_attribute('id'))  # 找到frmReport这个房间
    driver.switch_to.frame(iframe)  # 进到frmReport这个房间
    # id定位方式获取整个表格对象
    find_tbody = driver.find_elements(By.TAG_NAME, "tbody")
    diverse = driver.find_element(By.ID, find_tbody[0].get_attribute('id'))  # 找到tbody
    # # 通过标签名获取表格中所有行
    trlist = diverse.find_elements(By.TAG_NAME, 'tr')
    for row in trlist:
        # 遍历行对象，获取每一个行中所有的课对象
        tdlist = row.find_elements(By.TAG_NAME, 'td')
        for col in tdlist:
            # 输出课
            print(col.text + '\t', end='')
            if col.text.find(course) != -1:
                # 点击选择按钮
                try:
                    # 点击选择按钮
                    row.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_course_name).click()
                except Exception:
                    raise error.course_have_select_error
                # 返回父级frame
                driver.switch_to.parent_frame()
                # 筛选动态iframe
                dynamic_frame = driver.find_elements(By.TAG_NAME, "iframe")
                while len(dynamic_frame) != 4:
                    dynamic_frame = driver.find_elements(By.TAG_NAME, "iframe")
                    if len(dynamic_frame) == 4:
                        break
                #  # 进到动态iframe房间
                driver.switch_to.frame(dynamic_frame[3].get_attribute('id'))
                # 进入动态iframe嵌套的iframe
                frame = driver.find_elements(By.TAG_NAME, "iframe")
                driver.switch_to.frame(frame[0].get_attribute('id'))
                # 点击选择按钮框
                driver.find_element(By.NAME, "radio").click()
                # 退出当前iframe房间，返回父级iframe房间
                driver.switch_to.parent_frame()
                # 提交选课
                XPath = '//*[@value="' + IniConfBoj.mylocal_educational_system_course_sumbit_name + '"]'
                driver.find_element(By.XPATH, XPath).click()
                try:
                    alert = driver.switch_to.alert
                    raise error.course_have_select_error
                except NoAlertPresentException:
                    return True
                break
        else:  # 仅在内循环不中断时执行
            print("\n", end='')
            continue
        break
    return True


#  开始填写课程
def fill_course(IniConfBoj, course):
    # 填写课程
    sleep(float(IniConfBoj.mylocal_main_time))
    driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_course_id).clear()
    driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_course_id).send_keys(course)
    sleep(float(IniConfBoj.mylocal_main_time))
    # # 检索
    XPath = '//*[@value="' + IniConfBoj.mylocal_educational_system_searching_name + '"]'
    driver.find_element(By.XPATH, XPath).click()
    sleep(float(IniConfBoj.mylocal_main_time))
    # 抢课
    try:
        succeed = select_course(course, driver, IniConfBoj)
        if succeed:
            return True
        driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_course_name)
    except error.course_have_select_error as e:
        logger.warning("已经有该课啦\t")
        raise error.select_error()
    except Exception as e:
        raise error.select_error()


def error_way():
    sleep(float(IniConfBoj.mylocal_main_time))
    try:
        driver.switch_to.alert.accept()
    except:
        pass
    sleep(float(IniConfBoj.mylocal_main_time))
    driver.switch_to.default_content()
    sleep(float(IniConfBoj.mylocal_main_time))
    driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_out_system).click()
    sleep(float(IniConfBoj.mylocal_main_time))
    driver.switch_to.alert.accept()
    sleep(float(IniConfBoj.mylocal_main_time))


def post_image(image_path, url):
    contentType = mimetypes.guess_type(image_path)[0]
    files = []
    f1 = ('img', (image_path, open(image_path, 'rb'), contentType))
    files.append(f1)
    ret = requests.request("post", url, files=files)
    print(ret)


if __name__ == '__main__':
    try:
        # 读取配置文件
        filename = './src/conf/basics.ini'
        IniConfBoj = IniConf(filename=filename)
        # 日志初始化
        logger = logging.getLogger('test')
        logger.setLevel(level=logging.DEBUG)
        # 日志输出格式
        formatter = logging.Formatter('%(asctime)s - %(levelname)s: %(message)s')
        # 文件输出日志
        file_handler = logging.FileHandler('Rob.log')
        file_handler.setLevel(level=logging.INFO)
        file_handler.setFormatter(formatter)
        # 控制台输出格式
        stream_handler = logging.StreamHandler()
        stream_handler.setLevel(logging.DEBUG)
        stream_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
        logger.addHandler(stream_handler)
        # 打开浏览器
        driver = webdriver.Edge()
        driver.get("http://jwc.jzxy.edu.cn/")
        driver.maximize_window()
        # #进入登录页面
        enter_login(IniConfBoj)
        while True:
            response = requests.get(IniConfBoj.important_url + "/student")
            data = json.loads(response.text)
            if data['code'] == 1:
                # 请求账户信息
                json_student = json.dumps(data['data'])
                student = ParseJsonToObj(json_student, Student)
                logger.info("学号：" + student.id + " 开始抢课" + " 密码：" + student.password)
                # 输入账号密码
                try:
                    input_login_course(IniConfBoj, student.id, student.password)
                except error.login_error_password as e:
                    logger.warning("登录失败\t" + student.id + "  密码错误：" + student.password)
                    driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_confirm_button).click()
                    continue
                # 进入教务系统进入选课
                try:
                    begin_select_course(IniConfBoj)
                except Exception as e:
                    logger.error("进入教务系统筛选异常\t" + student.id + "  密码：" + student.password)
                    driver.switch_to.default_content()
                    sleep(float(IniConfBoj.mylocal_main_time))
                    driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_out_system).click()
                    sleep(float(IniConfBoj.mylocal_main_time))
                    driver.switch_to.alert.accept()
                    sleep(float(IniConfBoj.mylocal_main_time))
                    continue
                #  开始填写课程
                logger.info("学号：" + student.id + " 开始填写课程，加急抢中")
                if student.count == '1':
                    try:
                        result = fill_course(IniConfBoj, student.course1)
                        driver.switch_to.parent_frame()
                        try:
                            sleep(float(IniConfBoj.mylocal_main_time))
                            driver.switch_to.alert.accept()
                            driver.find_element(By.XPATH, '//*[@alt="关闭"]').click()
                        except:
                            pass
                        driver.switch_to.default_content()
                        # 跳转主控
                        driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_mian_name).click()
                        # 切换到主控
                        frame = driver.find_elements(By.TAG_NAME, "iframe")
                        iframe = driver.find_element(By.ID, frame[0].get_attribute('id'))  # 找到frmDesk这个房间
                        driver.switch_to.frame(iframe)  # 进入到frmDesk这个房间
                        # 点击网上选课
                        driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_select_name).click()
                        # 点击按选课结果
                        driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_course_result_id).click()
                        picture_url = driver.get_screenshot_as_file(f'./img/{student.id}.png')
                        url = f'{IniConfBoj.important_url}/common/img/{student.id}'
                        image_path = f"./img/{student.id}.png"
                        post_image(image_path, url)
                        requests.get(f'{IniConfBoj.important_url}/student/amend/{student.id}')
                        driver.switch_to.default_content()
                        sleep(float(IniConfBoj.mylocal_main_time))
                        driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_out_system).click()
                        sleep(float(IniConfBoj.mylocal_main_time))
                        driver.switch_to.alert.accept()
                        logger.info(f'学号：{student.id}--抢课成功')
                        continue
                    except error.select_error as e:
                        logger.error("账号选课重复或已到达最大学分错误\t" + student.id + "  密码：" + student.password)
                        error_way()
                        continue
                if student.count == '2':
                    try:
                        fill_course(IniConfBoj, student.course1)
                    except error.select_error as e:
                        driver.switch_to.parent_frame()
                        sleep(float(IniConfBoj.mylocal_main_time))
                        try:
                            driver.switch_to.alert.accept()
                            driver.find_element(By.XPATH, '//*[@alt="关闭"]').click()
                        except:
                            pass
                    try:
                        driver.switch_to.parent_frame()
                        try:
                            sleep(float(IniConfBoj.mylocal_main_time))
                            driver.switch_to.alert.accept()
                            driver.find_element(By.XPATH, '//*[@alt="关闭"]').click()
                        except:
                            pass
                        driver.switch_to.default_content()
                        frame = driver.find_elements(By.TAG_NAME, "iframe")
                        iframe = driver.find_element(By.ID, frame[0].get_attribute('id'))  # 找到frmDesk这个房间
                        driver.switch_to.frame(iframe)  # 进到frmDesk这个房间
                        result = fill_course(IniConfBoj, student.course2)
                        driver.switch_to.parent_frame()
                        try:
                            sleep(float(IniConfBoj.mylocal_main_time))
                            driver.switch_to.alert.accept()
                            driver.find_element(By.XPATH, '//*[@alt="关闭"]').click()
                        except:
                            pass
                        driver.switch_to.default_content()
                        # 跳转主控
                        driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_mian_name).click()
                        # 切换到主控
                        frame = driver.find_elements(By.TAG_NAME, "iframe")
                        iframe = driver.find_element(By.ID, frame[0].get_attribute('id'))  # 找到frmDesk这个房间
                        driver.switch_to.frame(iframe)  # 进入到frmDesk这个房间
                        # 点击网上选课
                        driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_system_select_name).click()
                        # 点击按选课结果
                        driver.find_element(By.ID, IniConfBoj.mylocal_educational_system_course_result_id).click()
                        picture_url = driver.get_screenshot_as_file(f'./img/{student.id}.png')
                        url = f'{IniConfBoj.important_url}/common/img/{student.id}'
                        image_path = f"./img/{student.id}.png"
                        post_image(image_path, url)
                        requests.get(f'{IniConfBoj.important_url}/student/amend/{student.id}')
                        driver.switch_to.default_content()
                        sleep(float(IniConfBoj.mylocal_main_time))
                        driver.find_element(By.LINK_TEXT, IniConfBoj.mylocal_educational_out_system).click()
                        sleep(float(IniConfBoj.mylocal_main_time))
                        driver.switch_to.alert.accept()
                        logger.info(f'学号：{student.id}--抢课成功')
                        continue
                    except error.select_error as e:
                        logger.error("账号选课重复或已到达最大学分错误\t" + student.id + "  密码：" + student.password)
                        error_way()
                        continue
            if data['code'] == 0:
                print(data['msg'])
                sleep(1)
                print("正在等待数据中，请稍后......")
    except Exception as e:
        logger.error("程序出了错误" + e)
